home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.004 / xemacs-1 / xemacs-19.13 / src / alloca.s < prev    next >
Encoding:
Text File  |  1995-03-01  |  9.8 KB  |  355 lines

  1. /* `alloca' standard 4.2 subroutine for 68000's and 16000's and others.
  2.    Also has _setjmp and _longjmp for pyramids.
  3.    Copyright (C) 1985, 1986, 1988 Free Software Foundation, Inc.
  4.  
  5. This file is part of XEmacs.
  6.  
  7. XEmacs is free software; you can redistribute it and/or modify it
  8. under the terms of the GNU General Public License as published by the
  9. Free Software Foundation; either version 2, or (at your option) any
  10. later version.
  11.  
  12. XEmacs is distributed in the hope that it will be useful, but WITHOUT
  13. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with XEmacs; see the file COPYING.  If not, write to the Free
  19. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /* Synched up with: FSF 19.28. */
  22.  
  23. /* Both 68000 systems I have run this on have had broken versions of alloca.
  24.    Also, I am told that non-berkeley systems do not have it at all.
  25.    So replace whatever system-provided alloca there may be
  26.    on all 68000 systems.  */
  27.  
  28. #define NOT_C_CODE
  29. #ifdef emacs
  30. #include <config.h>
  31. #else
  32. #include "config.h"
  33. #endif
  34.  
  35. #ifndef HAVE_ALLOCA  /* define this to use system's alloca */
  36.  
  37. #ifndef hp9000s300
  38. #ifndef m68k
  39. #ifndef m68000
  40. #ifndef WICAT
  41. #ifndef ns32000
  42. #ifndef ns16000
  43. #ifndef sequent
  44. #ifndef pyramid
  45. #ifndef ATT3B5
  46. #ifndef XENIX
  47. you
  48. lose!!
  49. #endif /* XENIX */
  50. #endif /* ATT3B5 */
  51. #endif /* pyramid */
  52. #endif /* sequent */
  53. #endif /* ns16000 */
  54. #endif /* ns32000 */
  55. #endif /* WICAT */
  56. #endif /* m68000 */
  57. #endif /* m68k */
  58. #endif /* hp9000s300 */
  59.  
  60.  
  61. #ifdef hp9000s300
  62. #ifdef OLD_HP_ASSEMBLER
  63.     data
  64.     text
  65.     globl    _alloca
  66. _alloca    
  67.     move.l    (sp)+,a0    ; pop return addr from top of stack
  68.     move.l    (sp)+,d0    ; pop size in bytes from top of stack
  69.     add.l    #ROUND,d0    ; round size up to long word
  70.     and.l    #MASK,d0    ; mask out lower two bits of size
  71.     sub.l    d0,sp        ; allocate by moving stack pointer
  72.     tst.b    PROBE(sp)    ; stack probe to allocate pages
  73.     move.l    sp,d0        ; return pointer
  74.     add.l    #-4,sp        ; new top of stack
  75.     jmp    (a0)        ; not a normal return
  76. MASK    equ    -4        ; Longword alignment
  77. ROUND    equ    3        ; ditto
  78. PROBE    equ    -128        ; safety buffer for C compiler scratch
  79.     data
  80. #else /* new hp assembler syntax */
  81. /*
  82.   The new compiler does "move.m <registers> (%sp)" to save registers,
  83.     so we must copy the saved registers when we mung the sp.
  84.   The old compiler did "move.m <register> <offset>(%a6)", which
  85.     gave us no trouble
  86.  */
  87.     text
  88.     set    PROBE,-128    # safety for C frame temporaries
  89.     set    MAXREG,22    # d2-d7, a2-a5, fp2-fp7 may have been saved
  90.     global    _alloca
  91. _alloca:
  92.     mov.l    (%sp)+,%a0    # return address
  93.     mov.l    (%sp)+,%d0    # number of bytes to allocate
  94.     mov.l    %sp,%a1        # save old sp for register copy
  95.     mov.l    %sp,%d1        # compute new sp
  96.     sub.l    %d0,%d1        # space requested
  97.     and.l    &-4,%d1        # round down to longword
  98.     sub.l    &MAXREG*4,%d1    # space for saving registers
  99.     mov.l    %d1,%sp        # save new value of sp
  100.     tst.b    PROBE(%sp)    # create pages (sigh)
  101.     mov.l    %a2,%d1        # save reg a2
  102.     mov.l    %sp,%a2
  103.     move.w    &MAXREG-1,%d0
  104. copy_regs_loop:            /* save caller's saved registers */
  105.     mov.l    (%a1)+,(%a2)+
  106.     dbra    %d0,copy_regs_loop
  107.     mov.l    %a2,%d0        # return value
  108.     mov.l    %d1,%a2        # restore a2
  109.     add.l    &-4,%sp        # adjust tos
  110.     jmp    (%a0)        # rts
  111. #endif /* new hp assembler */
  112. #else
  113. #ifdef m68k            /* SGS assembler totally different */
  114.     file    "alloca.s"
  115.     global    alloca
  116. alloca:
  117. #ifdef MOTOROLA_DELTA
  118. /* slightly modified version of alloca to motorola sysV/68 pcc - based
  119.    compiler. 
  120.    this compiler saves used registers relative to %sp instead of %fp.
  121.    alright, just make new copy of saved register set whenever we allocate
  122.    new space from stack..
  123.    this is true at last until SVR3V7 . bug has reported to Motorola. */
  124.     set    MAXREG,10    # max no of registers to save (d2-d7, a2-a5)
  125.         mov.l   (%sp)+,%a1    # pop return addr from top of stack
  126.         mov.l   (%sp)+,%d0    # pop size in bytes from top of stack
  127.     mov.l    %sp,%a0        # save stack pointer for register copy
  128.         addq.l  &3,%d0        # round size up to long word
  129.         andi.l  &-4,%d0        # mask out lower two bits of size
  130.     mov.l    %sp,%d1        # compute new value of sp to d1
  131.         sub.l    %d0,%d1        # pseudo-allocate by moving stack pointer
  132.     sub.l    &MAXREG*4,%d1    # allocate more space for saved regs.
  133.     mov.l    %d1,%sp        # actual allocation.
  134.     move.w    &MAXREG-1,%d0    # d0 counts saved regs.
  135.     mov.l    %a2,%d1        # preserve a2.
  136.     mov.l    %sp,%a2        # make pointer to new reg save area.
  137. copy_regs_loop:         # copy stuff from old save area.
  138.     mov.l    (%a0)+,(%a2)+    # save saved register
  139.     dbra    %d0,copy_regs_loop
  140.         mov.l   %a2,%a0        # now a2 is start of allocated space.
  141.     mov.l    %a2,%d0        # return it in both a0 and d0 to play safe.
  142.     mov.l    %d1,%a2        # restore a2.
  143.         subq.l  &4,%sp        # new top of stack
  144.         jmp     (%a1)        # far below normal return
  145. #else /* not MOTOROLA_DELTA */
  146.     mov.l    (%sp)+,%a1    # pop return addr from top of stack
  147.     mov.l    (%sp)+,%d0    # pop size in bytes from top of stack
  148.     add.l    &R%1,%d0    # round size up to long word
  149.     and.l    &-4,%d0        # mask out lower two bits of size
  150.     sub.l    %d0,%sp        # allocate by moving stack pointer
  151.     tst.b    P%1(%sp)    # stack probe to allocate pages
  152.     mov.l    %sp,%a0        # return pointer as pointer
  153.     mov.l    %sp,%d0        # return pointer as int to avoid disaster
  154.     add.l    &-4,%sp        # new top of stack
  155.     jmp    (%a1)        # not a normal return
  156.     set    S%1,64        # safety factor for C compiler scratch
  157.     set    R%1,3+S%1    # add to size for rounding
  158.     set    P%1,-132    # probe this far below current top of stack
  159. #endif /* not MOTOROLA_DELTA */
  160.  
  161. #else /* not m68k */
  162.  
  163. #ifdef m68000
  164.  
  165. #ifdef WICAT
  166. /*
  167.  * Registers are saved after the corresponding link so we have to explicitly
  168.  * move them to the top of the stack where they are expected to be.
  169.  * Since we do not know how many registers were saved in the calling function
  170.  * we must assume the maximum possible (d2-d7,a2-a5).  Hence, we end up
  171.  * wasting some space on the stack.
  172.  *
  173.  * The large probe (tst.b) attempts to make up for the fact that we have
  174.  * potentially used up the space that the caller probed for its own needs.
  175.  */
  176.     .procss m0
  177.     .config "68000 1"
  178.     .module    _alloca
  179. MAXREG:    .const    10
  180.     .sect    text
  181.     .global    _alloca
  182. _alloca:
  183.     move.l    (sp)+,a1    ; pop return address
  184.     move.l    (sp)+,d0    ; pop allocation size
  185.     move.l    sp,d1        ; get current SP value
  186.     sub.l    d0,d1        ; adjust to reflect required size...
  187.     sub.l    #MAXREG*4,d1    ; ...and space needed for registers
  188.     and.l    #-4,d1        ; backup to longword boundry
  189.     move.l    sp,a0        ; save old SP value for register copy
  190.     move.l    d1,sp        ; set the new SP value
  191.     tst.b    -4096(sp)    ; grab an extra page (to cover caller)
  192.     move.l    a2,d1        ; save callers register
  193.     move.l    sp,a2
  194.     move.w    #MAXREG-1,d0    ; # of longwords to copy
  195. loop:    move.l    (a0)+,(a2)+    ; copy registers...
  196.     dbra    d0,loop        ; ...til there are no more
  197.     move.l    a2,d0        ; end of register area is addr for new space
  198.     move.l    d1,a2        ; restore saved a2.
  199.     addq.l    #4,sp        ; caller will increment sp by 4 after return.
  200.     move.l    d0,a0        ; return value in both a0 and d0.
  201.     jmp    (a1)
  202.     .end    _alloca
  203. #else
  204.  
  205. /* Some systems want the _, some do not.  Win with both kinds.  */
  206. .globl    _alloca
  207. _alloca:
  208. .globl    alloca
  209. alloca:
  210.     movl    sp@+,a0
  211.     movl    a7,d0
  212.     subl    sp@,d0
  213.     andl    #~3,d0
  214.     movl    d0,sp
  215.     tstb    sp@(0)        /* Make stack pages exist  */
  216.                 /* Needed on certain systems
  217.                    that lack true demand paging */
  218.     addql    #4,d0
  219.     jmp    a0@
  220.  
  221. #endif /* not WICAT */
  222. #endif /* m68000 */
  223. #endif /* not m68k */
  224. #endif /* not hp9000s300 */
  225.  
  226. #if defined (ns16000) || defined (ns32000)
  227.  
  228.     .text
  229.     .align    2
  230. /* Some systems want the _, some do not.  Win with both kinds.  */
  231. .globl    _alloca
  232. _alloca:
  233. .globl    alloca
  234. alloca:
  235.  
  236. /* Two different assembler syntaxes are used for the same code
  237.     on different systems.  */
  238.  
  239. #ifdef sequent
  240. #define IM
  241. #define REGISTER(x) x
  242. #else
  243. #ifdef NS5   /* ns SysV assembler */
  244. #define IM $
  245. #define REGISTER(x) x
  246. #else
  247. #define IM $
  248. #define REGISTER(x) 0(x)
  249. #endif
  250. #endif
  251.  
  252. /*
  253.  * The ns16000 is a little more difficult, need to copy regs.
  254.  * Also the code assumes direct linkage call sequence (no mod table crap).
  255.  * We have to copy registers, and therefore waste 32 bytes.
  256.  *
  257.  * Stack layout:
  258.  * new    sp ->    junk    
  259.  *         registers (copy)
  260.  *    r0 ->    new data        
  261.  *         |       (orig retval)
  262.  *         |      (orig arg)
  263.  * old  sp ->    regs      (orig)
  264.  *        local data
  265.  *    fp ->    old fp
  266.  */
  267.  
  268.     movd    tos,r1        /*  pop return addr */
  269.     negd    tos,r0        /*  pop amount to allocate */
  270.     sprd    sp,r2
  271.     addd    r2,r0
  272.     bicb    IM/**/3,r0    /*  4-byte align */
  273.     lprd    sp,r0
  274.     adjspb    IM/**/36    /*  space for regs, +4 for caller to pop */
  275.     movmd    0(r2),4(sp),IM/**/4    /*  copy regs */
  276.     movmd    0x10(r2),0x14(sp),IM/**/4
  277.     jump    REGISTER(r1)    /* funky return */
  278. #endif /* ns16000 or ns32000 */
  279.  
  280. #ifdef pyramid
  281.  
  282. .globl _alloca
  283.  
  284. _alloca: addw $3,pr0    # add 3 (dec) to first argument
  285.     bicw $3,pr0    # then clear its last 2 bits
  286.     subw pr0,sp    # subtract from SP the val in PR0
  287.     andw $-32,sp    # keep sp aligned on multiple of 32.
  288.     movw sp,pr0    # ret. current SP
  289.     ret
  290.  
  291. #ifdef PYRAMID_OLD /* This isn't needed in system version 4.  */
  292. .globl __longjmp
  293. .globl _longjmp
  294. .globl __setjmp
  295. .globl _setjmp
  296.  
  297. __longjmp: jump _longjmp
  298. __setjmp:  jump _setjmp
  299. #endif
  300.  
  301. #endif /* pyramid */
  302.  
  303. #ifdef ATT3B5
  304.  
  305.     .align 4
  306.     .globl alloca
  307.  
  308. alloca:
  309.     movw %ap, %r8
  310.     subw2 $9*4, %r8
  311.     movw 0(%r8), %r1    /* pc */
  312.     movw 4(%r8), %fp
  313.     movw 8(%r8), %sp
  314.     addw2 %r0, %sp /* make room */
  315.     movw %sp, %r0 /* return value */
  316.     jmp (%r1) /* continue... */
  317.  
  318. #endif /* ATT3B5 */
  319.  
  320. #ifdef XENIX
  321.  
  322. .386
  323.  
  324. _TEXT segment dword use32 public 'CODE'
  325. assume   cs:_TEXT
  326.  
  327. ;-------------------------------------------------------------------------
  328.  
  329. public _alloca
  330. _alloca proc near
  331.  
  332.     pop    ecx        ; return address
  333.     pop    eax        ; amount to alloc
  334.     add    eax,3        ; round it to 32-bit boundary
  335.     and    al,11111100B    ;
  336.     mov    edx,esp        ; current sp in edx
  337.     sub    edx,eax        ; lower the stack
  338.     xchg    esp,edx        ; start of allocation in esp, old sp in edx
  339.     mov    eax,esp        ; return ptr to base in eax
  340.     push    [edx+8]        ; save poss. stored reg. values (esi,edi,ebx)
  341.     push    [edx+4]        ;  on lowered stack
  342.     push    [edx]        ;
  343.     sub    esp,4        ; allow for 'add esp, 4'
  344.     jmp    ecx        ; jump to return address
  345.  
  346. _alloca endp
  347.  
  348. _TEXT    ends
  349.  
  350. end
  351.  
  352. #endif /* XENIX */
  353.  
  354. #endif /* not HAVE_ALLOCA */
  355.